home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 076-100 / scopedisk83 / popcli4 / popmain.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  18KB  |  577 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors.                                                    */
  5. /* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
  6. /* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
  7. /* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */ 
  8. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  9. /*
  10.  * VERY loosely based on the input.device example by Rob Peck, 12/1/85
  11.  */
  12.  
  13. #include "popcli.h"
  14. #include "popbug.h"
  15. #include "cback.h"
  16.  
  17.  
  18. #ifdef BUGMACROS
  19. #define __BugWindow (*(BPTR *)"BUG") /* 4 bytes, big enuf for a BPTR */
  20. #endif
  21.  
  22. /************************************************************************/
  23. /* the main program to do the popcli stuff                              */
  24. /************************************************************************/
  25.  
  26. #undef global   /* Since it really is local in this routine */
  27.  
  28. void _main()
  29.    {
  30.    struct cbackstr     *cback;
  31.  
  32.    struct MsgPort      *port;
  33.    int                 stay = 0;
  34.    int                 shutdown;
  35.    short               timeout;
  36.    struct OURMSG       *msg;
  37.    register CommandBlock *cb;
  38.    int                 key;
  39.    struct Process      *us;
  40. #ifdef BUGMACROS
  41.    BPTR                bugwindow;
  42. #endif
  43.  
  44.    BPTR  nullfh;
  45.    ULONG sig, portsig, timersig;
  46.    struct timerequest *timerreq;
  47.    struct MsgPort     *timerport;
  48.    struct MsgPort     *inputDevPort;
  49.    struct IOStdReq    *inputRequestBlock;
  50.    struct Interrupt    handlerStuff;
  51.    GLOBAL_DATA         global;
  52.    struct Process     *SyncProcess;
  53.    int                 SyncSignal;
  54.    char               *cmd;
  55.    int                 cmdlen;
  56.    struct RexxMsg     *amsg;
  57.    struct OURMSG       pmsg;   /* for AREXX message parsing */
  58.  
  59.    int                 rc;
  60.  
  61.    memset( (char *)&global, 0, sizeof(global) );
  62.    
  63.    DOSBase = (struct DosBase *)OpenLibrary("dos.library",0);
  64.  
  65.    global.blanksignum  = -1;
  66.    timerreq            = NULL;
  67.    timerport           = NULL;
  68.    inputDevPort        = NULL;
  69.    inputRequestBlock   = NULL;
  70.    msg                 = NULL;
  71.  
  72.    timeout             = DEFTIME;
  73.  
  74.    /* Fetch our arguments from the wild blue yonder */
  75.    us = (struct Process *)FindTask(0);
  76.    us->pr_ConsoleTask = NULL; 
  77.    WaitPort( &(us->pr_MsgPort) );
  78.    cback = (struct cbackstr *)GetMsg( &(us->pr_MsgPort) );
  79.  
  80.    global.stdout = cback->stdout;
  81.  
  82.    /* now see if we are already installed */
  83.    if ((port = FindPort(PORTNAME)) == NULL)
  84.    {
  85.       stay = 1; /* remember to hang around when we are done */
  86. #ifdef BUGMACROS
  87.       bugwindow = Open(BUGWINDOW,MODE_NEWFILE);
  88.       memcpy( "BUG", (char *)&bugwindow, 4 );/* __BugWindow = bugwindow; */
  89. #endif
  90.       BUG(("Setting stay to 1 - first time here\n"));
  91.  
  92.       /* not installed, we need to install our own port */
  93.       if ((port = MyCreatePort(&global, PORTNAME)) == NULL)
  94.          goto abort;
  95.  
  96.       /* Tell everybody we're here... */
  97.       popbanner( &global );
  98.    }
  99. #ifdef BUGMACROS
  100.    else
  101.    {
  102.       memcpy( "BUG", (char *)&global.stdout, 4 );
  103.    }
  104. #endif
  105.  
  106.    /* Bit of a kludge... remove the trailing "\n" so we don't have to */
  107.    /* muck with it in popparse(). Put a null on, too; and we can't    */
  108.    /* overwrite because there may not be enough room.                 */
  109.    cmdlen = cback->cmdlen;
  110.    cmd = AllocMem( cmdlen + 1, 0 );
  111.    memcpy( cmd, cback->cmd, cmdlen );
  112.  
  113.    if (cmd[cmdlen-1] == '\n')
  114.       cmd[cmdlen-1] = '\0';
  115.    else
  116.       cmd[cmdlen] = '\0';
  117.  
  118.    SyncProcess = cback->SyncProcess;
  119.    SyncSignal = cback->SyncSignal;
  120.  
  121.    FreeMem( (char *)cback, cback->msgpart.mn_Length );
  122.  
  123.    /* Save port for handler to use */
  124.    global.execport = port;
  125.  
  126.    /* now send the parameter to the waiting program */
  127.    if ((msg = (struct OURMSG *)
  128.               AllocMem(sizeof(struct OURMSG), MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
  129.       goto abort;
  130.    /* fill in the message information */
  131.    msg->msgpart.mn_Length = sizeof(struct OURMSG);
  132.  
  133.    BUG(("Command to parse: `%s'\n", cmd));
  134.    rc = popparse( &global, cmd, msg );
  135.  
  136.    /* We're done with the command line */
  137.    FreeMem( cmd, cmdlen+1 );
  138.  
  139.    if (rc == SHUTDOWN)
  140.    {
  141.       /* Print shutting down message */
  142.       poptrailer( &global );
  143.    }
  144.  
  145.    /* Get stack size and stuff from our parent, if we're the server */
  146.    if (stay)
  147.       copyproc( &global, us, SyncProcess );
  148.  
  149.    /* Let the original window go away */
  150.    if (global.stdout)
  151.       Close(global.stdout);
  152.    global.stdout = 0;
  153.  
  154.    /* We got everything, so it's safe to let the parent go away */
  155.    if (SyncSignal != -1)
  156.    {
  157.       Signal((struct Task *)SyncProcess, 1<<SyncSignal);
  158.       SyncSignal = -1;
  159.    }
  160.  
  161.    global.blankscreen = NULL;
  162.    if (stay && msg->interval == 0)
  163.       msg->interval = DEFTIME;
  164.  
  165.    BUG(("MSG TO SEND:\n"));
  166.    BUG(("   Type = %d\n", msg->type));
  167.    BUG(("   Key  = %d\n", msg->key));
  168.    BUG(("   Interval = %d\n", msg->interval));
  169.    BUG(("   minmem = %d\n", msg->minmem << 10));
  170.    BUG(("   minchip = %d\n", msg->minchip << 10));
  171.    BUG(("   CmdFlags = %02X\n", msg->cmdflags));
  172.    BUG(("   Command = `%s'\n", msg->command));
  173.  
  174.  
  175.    PutMsg(port,(struct Message *)msg);
  176.  
  177.    msg = NULL;
  178.  
  179.    /* If we're told to go away */
  180.    if ((rc == SHUTDOWN) || (rc == LEAVE) || !stay)
  181.    {
  182.       goto abort;
  183.    }
  184.  
  185.    global.noevents = 0;
  186.  
  187.    /* set the input and output streams to 0 so execute doen't complain */
  188.    nullfh = Open("NIL:", MODE_NEWFILE);
  189.  
  190.    if (((inputDevPort = MyCreatePort(&global,NULL)) == NULL)                 ||
  191.  
  192.       ((inputRequestBlock =
  193.           CreateIOReq(&global, inputDevPort, sizeof(struct IOStdReq))) == NULL)     ||
  194.  
  195.       ((timerport = MyCreatePort(&global,NULL)) == NULL)                     ||
  196.  
  197.       ((timerreq  = (struct timerequest *)
  198.           CreateIOReq(&global,timerport, sizeof(struct timerequest))) == NULL) ||
  199.  
  200.       ((global.blanksignum = AllocSignal(-1)) == -1)                       ||
  201.  
  202.       ((GfxBase = (GBasePtr)
  203.                   OpenLibrary("graphics.library", 0)) == NULL)             ||
  204.  
  205.       ((IntuitionBase = (IBasePtr)
  206.                         OpenLibrary("intuition.library", 0)) == NULL)      ||
  207.       OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timerreq, 0)  ||
  208.  
  209.       OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
  210.  
  211.       goto abort;
  212.  
  213.    handlerStuff.is_Data = (APTR)&global;
  214.    handlerStuff.is_Code = (VOID(*)())myhandler;
  215.    handlerStuff.is_Node.ln_Pri = 51;
  216.  
  217.    timersig            = (1 << timerport->mp_SigBit);
  218.    portsig             = (1 << port->mp_SigBit);
  219.    global.unblanksig   = 1 << global.blanksignum;
  220.  
  221.    inputRequestBlock->io_Command = IND_ADDHANDLER;
  222.    inputRequestBlock->io_Data    = (APTR)&handlerStuff;
  223.  
  224.    DoIO((struct IORequest *)inputRequestBlock);
  225.  
  226.    global.buddy = (struct Task *)us;
  227.  
  228.    QueueTimer(&global, timerreq, TIMEINTERVAL);
  229.  
  230.    /* All other fields in newscreen are 0 */
  231.    global.newscreen.Width    = 320;
  232.    global.newscreen.Height   = 30;
  233.    global.newscreen.Depth    = 1;
  234.    global.newscreen.BlockPen = 1;
  235.    global.newscreen.Type     = CUSTOMSCREEN;
  236.  
  237.    shutdown = 0;
  238.    while(!shutdown)
  239.       {
  240.       sig = Wait( portsig | global.unblanksig | timersig );
  241.  
  242.       /* see if we have anything to do */
  243.       while ((msg = (struct OURMSG *)GetMsg(port)) != NULL)
  244.       {
  245.      if ((msg->msgpart.mn_Node.ln_Name) &&
  246.              !strcmp(msg->msgpart.mn_Node.ln_Name, "REXX"))
  247.      {
  248.         /* we've got an ARexx message to parse. */
  249.         amsg = (struct RexxMsg *)msg;
  250.             BUG(("AREXX!! Command = `%s'\n", amsg->rm_Args[0]));
  251.  
  252.         rc = popparse( &global, amsg->rm_Args[0], &pmsg );
  253.         amsg->rm_Result1 = (rc == LEAVE) ? 5 : 0;
  254.         amsg->rm_Result2 = 0;
  255.         ReplyMsg( (struct Message *)amsg );
  256.  
  257.             /* So our normal msg processing code can handle it */
  258.         msg = &pmsg;
  259.          }
  260.      else
  261.         amsg = NULL;
  262.  
  263.          /* See which type of message we have */
  264.          switch( msg->type ) {
  265.  
  266.          /*----------------------------------------------------*/
  267.          case MSG_ADDKEY:
  268.             BUG(("*Add Key %d\n", msg->key));
  269.  
  270.             /* Because of parsing, we stick the interval information */
  271.             /* in with the MSG_ADDKEY. There should be a better way  */
  272.             /* to do this.                                           */
  273.             if (msg->interval)
  274.             {
  275.                timeout = msg->interval;
  276.                BUG((" Interval == %d ticks\n", timeout));
  277.             }
  278.  
  279.             /* If we already have defined this key, then we can   */
  280.             /* update its command, else add the key.              */
  281.             cb = global.keytab[msg->key];
  282.  
  283.             if (!cb)
  284.             {
  285.                /* Its not there, we need to add the key */
  286.                if (cb = (CommandBlock *)
  287.                              AllocMem(sizeof(CommandBlock),MEMF_PUBLIC))
  288.                {
  289.  
  290.                   /* Give new key the default command, if message has */
  291.                   /* no command.                                      */
  292.                   if (msg->command[0] == '\0')
  293.                      strcpy(cb->command, DEFCMD);
  294.  
  295.                   BUG((" creating <%d> at 0x%08lx\n", msg->key, (long)cb));
  296.                }
  297.                else
  298.                   BUG((" !!!! Can't alloc command block!!!\n"));
  299.  
  300.                global.keytab[msg->key] = cb;
  301.             }
  302.  
  303.             /* Update the key command, for new or old key */
  304.             if (cb)
  305.             {
  306.                cb->minmem   = msg->minmem;
  307.                cb->minchip  = msg->minchip;
  308.                cb->cmdflags = msg->cmdflags;
  309.  
  310.                if (cb && msg->command[0])
  311.                {
  312.                   strcpy(cb->command, msg->command);
  313.                }
  314.  
  315.                BUG((" New command = `%s'\n", cb->command));
  316.             }
  317.  
  318.             break;
  319.  
  320.          /*----------------------------------------------------*/
  321.          case MSG_DELKEY:
  322.             BUG(("*Delete Key %d\n", msg->key));
  323.  
  324.             cb = global.keytab[msg->key];
  325.         if (cb)
  326.         {
  327.                BUG(("  killing <%d> at 0x%08lx\n", msg->key, (long)cb));
  328.  
  329.                global.keytab[msg->key] = NULL;
  330.                FreeMem( (char *)cb, sizeof(CommandBlock) );
  331.             }
  332.             break;
  333.  
  334.          /*----------------------------------------------------*/
  335.          case MSG_EXECUTE:
  336.             BUG(("*Execute for key %d\n", msg->key));
  337.             cb = global.keytab[msg->key];
  338.  
  339.         if (cb)
  340.         {
  341.                BUG(("   Executing `%s'\n", cb->command));
  342.  
  343.                if (cb->minmem)
  344.                {
  345.                   BUG(("Public memory:  REQ: %8d, AVAIL: %8d\n",
  346.                                      cb->minmem  << 10,
  347.                                      AvailMem(MEMF_PUBLIC)));
  348.                }
  349.  
  350.                if (cb->minchip)
  351.                {
  352.                   BUG(("Chip memory:    REQ: %7d,  AVAIL: %7d\n",
  353.                                      cb->minchip << 10,
  354.                                      AvailMem(MEMF_CHIP)));
  355.                }
  356.  
  357.                if (((cb->minmem  == 0) ||
  358.                           ((AvailMem(MEMF_PUBLIC)>>10) >= cb->minmem )) &&
  359.                    ((cb->minchip == 0) ||
  360.                           ((AvailMem(MEMF_CHIP  )>>10) >= cb->minchip)))
  361.                {
  362.                   if (!(cb->cmdflags & FLAG_NOWB2F))
  363.                      WBenchToFront();
  364.  
  365.                   if (! Execute(cb->command, nullfh, nullfh))
  366.                      DisplayBeep(NULL);
  367.                }
  368.                else
  369.                   DisplayBeep(NULL);
  370.             }
  371.         break;
  372.  
  373.          /*----------------------------------------------------*/
  374.          case MSG_SHUTDOWN:
  375.             BUG(("*Quit: Shut UP!!\n"));
  376.  
  377.             /* Cause us to drop out of loop when we're thru */
  378.             shutdown = 1;
  379.             break;
  380.  
  381.          /*----------------------------------------------------*/
  382.          case MSG_BLANK:
  383.             BUG(("*BLANK it out!\n"));
  384.             if (global.blankscreen == NULL)
  385.             {
  386.                if ( (global.blankscreen = OpenScreen(&global.newscreen)) != NULL)
  387.                {
  388.                   BUG(("Screen OFF!!!!!\n"));
  389.                   SetRGB4(&(global.blankscreen->ViewPort), 0, 0, 0, 0);
  390.                   OFF_DISPLAY
  391.                }
  392.             }
  393.             break;
  394.  
  395.          /*----------------------------------------------------*/
  396.          case MSG_UNBLANK:
  397.             BUG(("*UNBLANK it back!\n"));
  398.             if (global.blankscreen)
  399.             {
  400.                CloseScreen(global.blankscreen);
  401.            ON_DISPLAY
  402.                global.blankscreen = NULL;
  403.                global.noevents = 0;
  404.             }
  405.             break;
  406.  
  407.          /*----------------------------------------------------*/
  408.          case MSG_SETTIME:
  409.             BUG(("*Timeout set to %d\n", msg->interval));
  410.             timeout = msg->interval;
  411.             break;
  412.  
  413.          /*----------------------------------------------------*/
  414.          default:
  415.             BUG(("HEY, I got an unknown message at %08lx!!!!!\n", msg));
  416.          }
  417.  
  418.          if (!amsg)
  419.             FreeMem((char *)msg, msg->msgpart.mn_Length);
  420.       }
  421.  
  422.       if ((sig & global.unblanksig) && global.blankscreen)
  423.          {
  424.          BUG(("Screen On\n"));
  425.  
  426.          CloseScreen(global.blankscreen);
  427.      ON_DISPLAY
  428.          global.blankscreen = NULL;
  429.          }
  430.  
  431.       if (sig & timersig)
  432.          {
  433.          /* get rid of the message */
  434.          (void)GetMsg(timerport);
  435.          QueueTimer(&global, timerreq, TIMEINTERVAL);
  436.  
  437.          if ((global.noevents++ >= timeout) && (global.blankscreen == NULL))
  438.             {
  439.             if ( (global.blankscreen = OpenScreen(&global.newscreen)) != NULL)
  440.                {
  441.                BUG(("Screen OFF!!!!!\n"));
  442.                SetRGB4(&(global.blankscreen->ViewPort), 0, 0, 0, 0);
  443.                OFF_DISPLAY
  444.                }
  445.             }
  446.          }
  447.  
  448.       /* Force our screen to front on a regular basis to handle something   */
  449.       /* that might put their stuff in front of us while we are supposed to */
  450.       /* Be blanking the screen.                                            */
  451.       if (global.blankscreen)
  452.          {
  453.          BUG(("Screen still off\n"));
  454. #if 1
  455.          if (((IBasePtr)IntuitionBase)->FirstScreen != global.blankscreen)
  456.             ScreenToFront(global.blankscreen);
  457. #endif
  458.          OFF_DISPLAY
  459.          }
  460.       }
  461.  
  462.    BUG(("Normal POPCLI shutdown beginning...\n"));
  463.  
  464. abort:
  465.  
  466.    if (stay)
  467.       BUG(("At `abort'...\n"));
  468.  
  469.    if (msg) FreeMem((char *)msg, msg->msgpart.mn_Length);
  470.    if (timerreq != NULL)
  471.       {
  472.       if (timerreq->tr_node.io_Device != NULL)
  473.          {
  474.          AbortIO( (struct IORequest *)timerreq );
  475.          CloseDevice((struct IORequest *)timerreq);
  476.          }
  477.       DeleteIOReq(&global, (struct IOStdReq *)timerreq);
  478.       }
  479.  
  480.    if (inputRequestBlock != NULL)
  481.       {
  482.       if (inputRequestBlock->io_Device != NULL)
  483.          {
  484.          inputRequestBlock->io_Command = IND_REMHANDLER;
  485.          inputRequestBlock->io_Data = (APTR)&handlerStuff;
  486.          DoIO((struct IORequest *)inputRequestBlock);
  487.  
  488.          CloseDevice((struct IORequest *)inputRequestBlock);
  489.          }
  490.       DeleteIOReq(&global, inputRequestBlock);
  491.       }
  492.  
  493.    if (timerport != NULL)          MyDeletePort(&global, timerport);
  494.    if (global.blanksignum != -1)   FreeSignal(global.blanksignum);
  495.    if (global.blankscreen != NULL) CloseScreen(global.blankscreen);
  496.    if (IntuitionBase != NULL)      CloseLibrary((struct Library *)IntuitionBase);
  497.    if (GfxBase != NULL)            CloseLibrary((struct Library *)GfxBase);
  498.    if (inputDevPort != NULL)       MyDeletePort(&global, inputDevPort);
  499.    if (stay && (port != NULL))
  500.    {
  501.       /* Empty the port before we trash it */
  502.       while (msg = (struct OURMSG *)GetMsg(port))   /* assign */
  503.          FreeMem( (char *)msg, msg->msgpart.mn_Length );
  504.  
  505.       MyDeletePort(&global, port);
  506.       BUG(("Port gone...\n"));
  507.    }
  508.  
  509.    if (global.stdout)
  510.       Close(global.stdout);
  511.    if (SyncSignal != -1)
  512.       Signal((struct Task *)SyncProcess, 1<<SyncSignal);
  513.  
  514.    if (stay)
  515.       {
  516.       /* NOTE: "prev" is really used as a "next" here */
  517.       for (key = 0; key < 256; key++)
  518.           {
  519.           if (cb = global.keytab[key])
  520.          {
  521.              BUG(("Deleting key <%d> at 0x%08lx\n", key, cb));
  522.  
  523.              FreeMem( (char *)cb, sizeof(CommandBlock) );
  524.          }
  525.           }
  526.       }
  527.  
  528.    if (nullfh)                     Close(nullfh);
  529.  
  530. #ifdef BUGMACROS
  531.    if (stay)
  532.    {
  533.       int paws = 1000000;
  534.  
  535.       BUG(("..bye bye"));
  536.       while(--paws>0);
  537.       Close(__BugWindow);
  538.    }
  539. #endif
  540.  
  541.    /* Free all our copyproc() stuff, if we were the server */
  542.    if (stay)
  543.       termproc( &global, (struct Process *)FindTask(NULL) );
  544.  
  545.    if (DOSBase)
  546.       CloseLibrary( (struct Library *)DOSBase );
  547. }
  548.  
  549. #ifdef BUGMACROS
  550. #undef DOSBase
  551.  
  552. void __stdargs myprintf(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  553. char    *fmt;
  554. long    a1, a2, a3, a4, a5, a6, a7, a8, a9;
  555. {
  556.     int            bytes;
  557.     char            buff[512];
  558.     struct DosLibrary    *DOSBase;
  559.  
  560.     if (__BugWindow <= 0) return(0);
  561.     
  562.     bytes = sprintf(buff, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  563.  
  564.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0);
  565.  
  566.     if (bytes < sizeof(buff))
  567.         Write(__BugWindow, buff, bytes);
  568.     else
  569.         Write(__BugWindow, "!!! msg too big - prepare to die\n",
  570.                 strlen("!!! msg too big - prepare to die\n"));
  571.  
  572.     CloseLibrary( (struct Library *)DOSBase );
  573.     return(0);
  574. }
  575. #endif
  576.  
  577.